<template>
	<div class="map-wrap">
		<div ref="map" class="map"></div>
	</div>
</template>

<script>
import L from 'leaflet'

const DEFAULT_CENTER = [20, 0]
const DEFAULT_ZOOM = 2.25

export default {
	name: 'MapView',
	props: {
		events: { type: Array, default: () => [] },
		pickMode: { type: Boolean, default: false },
		myLocation: { type: Object, default: null }
	},
	data() {
		return {
			map: null,
			markers: [],
			lines: [],
			myLocationMarker: null,
			movingMarkers: [],
			movingTimers: []
		}
	},
	watch: {
		events: {
			immediate: true,
			handler() {
				this.$nextTick(() => {
					this.renderMarkers()
					this.updateMyLocationLines()
				})
			}
		},
		myLocation() {
			this.updateMyLocationLines()
		}
	},
	mounted() { this.initMap() },
	beforeDestroy() { this.clearMarkers(); this.clearLines() },
	methods: {
		initMap() {
			this.map = L.map(this.$refs.map, {
				center: DEFAULT_CENTER,
				zoom: DEFAULT_ZOOM,
				zoomControl: false,
				minZoom: 2,
				worldCopyJump: true,
				maxBounds: [[-85, -180], [85, 180]],
				maxBoundsViscosity: 1.0
			})
			const primaryTiles = L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', { maxZoom: 19, attribution: '© OpenStreetMap contributors' })
			primaryTiles.on('tileerror', () => {
				// fallback to Carto if OSM blocked
				L.tileLayer('https://cartodb-basemaps-{s}.global.ssl.fastly.net/light_all/{z}/{x}/{y}.png', {
					maxZoom: 19,
					attribution: '© OpenStreetMap, © Carto'
				}).addTo(this.map)
			})
			primaryTiles.addTo(this.map)
			L.control.zoom({ position: 'bottomright' }).addTo(this.map)
			this.map.on('click', (e) => { if (this.pickMode) this.$emit('picked-location', { lat: e.latlng.lat, lng: e.latlng.lng }) })
			this.renderMarkers()
		},
		renderMarkers() {
			if (!this.map) return
			this.clearMarkers()
			for (const ev of this.events) {
				const isUpcoming = ev.status === 'upcoming'
				const imgUrl = ev.image || ''
				const thumbStyle = imgUrl ? `background-image:url('${imgUrl}')` : 'background:linear-gradient(135deg,#f7f2ea,#efe7da)'
                const html = '\n\t\t\t\t\t<div class="ev-marker">\n\t\t\t\t\t\t<div class="thumb" style="' + thumbStyle + '"></div>\n\t\t\t\t\t\t<div class="label ' + (isUpcoming ? 'upcoming' : 'past') + '">' + ev.city + '</div>\n\t\t\t\t\t</div>\n\t\t\t\t\t'
                const icon = L.divIcon({ html, className: 'ev-marker-wrap', iconSize: [1,1] })
				const marker = L.marker([ev.lat, ev.lng], { icon }).addTo(this.map)
				marker.on('click', () => this.$emit('open-event', ev))
				this.markers.push(marker)
			}
		},
		zoomToEvents() {
			if (!this.map || this.markers.length === 0) return
			const group = L.featureGroup(this.markers)
			this.map.fitBounds(group.getBounds().pad(0.2))
		},
		resetView() { if (this.map) this.map.setView(DEFAULT_CENTER, DEFAULT_ZOOM) },
		clearMarkers() { for (const m of this.markers) m.remove(); this.markers = [] },
		clearLines() {
			for (const l of this.lines) l.remove()
			this.lines = []
			if (this.myLocationMarker) { this.myLocationMarker.remove(); this.myLocationMarker = null }
			for (const m of this.movingMarkers) m.remove()
			this.movingMarkers = []
			for (const t of this.movingTimers) clearInterval(t)
			this.movingTimers = []
		},
		updateMyLocationLines() {
			if (!this.map) return
			this.clearLines()
			if (!this.myLocation) return
			// add red marker at picked location
			this.myLocationMarker = L.circleMarker([this.myLocation.lat, this.myLocation.lng], {
				radius: 6,
				color: '#ffffff',
				weight: 2,
				fillColor: '#E53935',
				fillOpacity: 1
			}).addTo(this.map)
			// draw red dashed lines and animate green triangle
			for (const ev of this.events.filter(e => e.status === 'upcoming')) {
				const start = [this.myLocation.lat, this.myLocation.lng]
				const end = [ev.lat, ev.lng]
				const line = L.polyline([start, end], { color: '#E53935', weight: 2, dashArray: '6,8', opacity: 0.95 }).addTo(this.map)
				this.lines.push(line)
				this.startMovingTriangle(start, end)
			}
		},
		startMovingTriangle(start, end) {
			// initial direction angle; will also keep alignment by recomputing along the same projected line
			const project = (ll) => this.map.latLngToLayerPoint(ll)
			const unproject = (pt) => this.map.layerPointToLatLng(pt)
			const p1 = project(start)
			const p2 = project(end)
			const angleRad0 = Math.atan2(p2.y - p1.y, p2.x - p1.x)
			const angleDeg0 = angleRad0 * 180 / Math.PI
			const icon = L.divIcon({
				html: '<div class="moving-triangle" style="transform: rotate(' + angleDeg0 + 'deg);"></div>',
				className: 'moving-triangle-wrap',
				iconSize: [12, 10],
				iconAnchor: [6, 10]
			})
			const mover = L.marker(start, { icon }).addTo(this.map)
			this.movingMarkers.push(mover)
			const durationMs = 4500
			const intervalMs = 60
			const steps = Math.max(1, Math.floor(durationMs / intervalMs))
			let step = 0
			const timer = setInterval(() => {
				step = (step + 1) % steps
				const t = step / steps
				// interpolate in screen space to stick to the straight red line
				const curr = L.point(
					p1.x + (p2.x - p1.x) * t,
					p1.y + (p2.y - p1.y) * t
				)
				const ll = unproject(curr)
				mover.setLatLng(ll)
			}, intervalMs)
			this.movingTimers.push(timer)
		},
		focusEvent(ev) {
			if (!this.map) return
			this.map.setView([ev.lat, ev.lng], 6, { animate: true })
		}
	}
}
</script>

<style scoped>
.map-wrap { height: 100%; width: 100%; }
.map { height: 100%; width: 100%; }
</style>
<style>
.ev-marker-wrap { background: transparent; border: none; }
.ev-marker { display: flex; flex-direction: column; align-items: center; gap: 6px; transform: translateY(-6px); }
.ev-marker .thumb { width: 48px; height: 48px; border-radius: 12px; background-size: cover; background-position: center; box-shadow: 0 6px 14px rgba(0,0,0,0.18); }
.ev-marker .label { display: inline-block; padding: 6px 10px; border-radius: 12px; font-size: 12px; line-height: 1; color: #111; box-shadow: 0 10px 22px rgba(0,0,0,0.10); background: #fff; }
.ev-marker .label.past { background: #ffffff; color: #111; }
.ev-marker .label.upcoming { background: #FFD94D; color: #111; }
/* moving triangle styles */
.moving-triangle-wrap { background: transparent; border: none; }
.moving-triangle {
	width: 0;
	height: 0;
	border-left: 6px solid transparent;
	border-right: 6px solid transparent;
	border-bottom: 10px solid #2ecc71; /* green */
}
</style> 